#include <iostream>
#include <functional>
#include <string>
#include <vector>
#include <type_traits>
#include <memory>

// 展示C++17的std::invoke功能

// 一个简单的类，用于演示调用成员函数和成员变量
class Person {
private:
    std::string m_name_;
    int m_age_;

public:
    Person(std::string name, int age) : m_name_(std::move(name)), m_age_(age) {}

    void introduce() const {
        std::cout << "  我的名字是" << m_name_ << "，今年" << m_age_ << "岁。\n";
    }

    void birthday() {
        ++m_age_;
        std::cout << "  庆祝" << m_name_ << "的生日！现在" << m_age_ << "岁了。\n";
    }

    std::string getName() const {
        return m_name_;
    }

    int getAge() const {
        return m_age_;
    }

    bool operator<(const Person& other) const {
        return m_age_ < other.m_age_;
    }

    std::string m_nickname_ = "无昵称";
};

// 一些全局函数，用于std::invoke演示
void greet(const std::string& name) {
    std::cout << "  你好，" << name << "！\n";
}

int add(int a, int b) {
    return a + b;
}

// 一个函数对象
struct Multiplier {
    int factor;
    
    Multiplier(int f) : factor(f) {}
    
    int operator()(int value) const {
        return value * factor;
    }
};

// 调用模板，通过std::invoke调用任何可调用对象
template<typename Callable, typename... Args>
auto call_and_print(Callable&& fn, Args&&... args) {
    std::cout << "  调用函数...\n";
    if constexpr (std::is_void_v<std::invoke_result_t<Callable, Args...>>) {
        // void返回类型
        std::invoke(std::forward<Callable>(fn), std::forward<Args>(args)...);
        std::cout << "  函数返回void\n";
    } else {
        // 非void返回类型
        auto result = std::invoke(std::forward<Callable>(fn), 
                                 std::forward<Args>(args)...);
        std::cout << "  返回结果: " << result << "\n";
        return result;
    }
}

void demonstrate_invoke() {
    std::cout << "  C++17 std::invoke 演示:\n\n";
    
    // 1. 调用普通函数
    std::cout << "  1. 调用普通函数:\n";
    std::invoke(greet, "张三");
    std::cout << "  通过std::invoke计算: 5 + 3 = " 
              << std::invoke(add, 5, 3) << "\n\n";
    
    // 2. 调用成员函数
    std::cout << "  2. 调用成员函数:\n";
    Person alice("Alice", 30);
    
    // 使用对象调用
    std::invoke(&Person::introduce, alice);
    
    // 使用指针调用
    Person* bob = new Person("Bob", 25);
    std::invoke(&Person::introduce, bob);
    delete bob;
    
    // 使用智能指针调用
    auto charlie = std::make_shared<Person>("Charlie", 35);
    std::invoke(&Person::introduce, charlie);
    
    // 调用会修改对象的成员函数
    std::invoke(&Person::birthday, alice);
    std::cout << "\n";
    
    // 3. 访问成员变量
    std::cout << "  3. 访问成员变量:\n";
    std::cout << "  昵称: " << std::invoke(&Person::m_nickname_, alice) << "\n";
    
    // 修改成员变量
    std::invoke(&Person::m_nickname_, alice) = "Alice猫猫";
    std::cout << "  修改后的昵称: " << std::invoke(&Person::m_nickname_, alice) << "\n\n";
    
    // 4. 调用函数对象
    std::cout << "  4. 调用函数对象:\n";
    Multiplier mult(10);
    std::cout << "  10 × 5 = " << std::invoke(mult, 5) << "\n";
    
    // 调用lambda
    auto divider = [](int a, int b) { return a / b; };
    std::cout << "  20 ÷ 4 = " << std::invoke(divider, 20, 4) << "\n\n";
    
    // 5. 使用std::function
    std::cout << "  5. 使用std::function:\n";
    std::function<int(int, int)> op = add;
    std::cout << "  通过std::function调用: 7 + 8 = " << std::invoke(op, 7, 8) << "\n";
    
    op = [](int a, int b) { return a * b; };
    std::cout << "  替换为lambda后调用: 7 × 8 = " << std::invoke(op, 7, 8) << "\n\n";
    
    // 6. 结合可变参数模板使用
    std::cout << "  6. 结合可变参数模板使用:\n";
    call_and_print(add, 10, 20);
    call_and_print(mult, 7);
    call_and_print(&Person::introduce, alice);
    call_and_print(&Person::getName, alice);
    std::cout << "\n";
    
    // 7. 实际应用
    std::cout << "  7. std::invoke的实际应用:\n";
    std::cout << "  - 实现泛型调用封装\n";
    std::cout << "  - 统一函数、成员函数、函数对象的调用方式\n";
    std::cout << "  - 实现回调系统\n";
    std::cout << "  - 与元编程结合使用\n";
    std::cout << "  - 简化反射实现\n";
    
    // 8. 与C++11/14的比较
    std::cout << "\n  8. 与C++11/14的比较:\n";
    std::cout << "  C++11/14需要使用复杂的模板技巧或std::bind来实现类似功能\n";
    std::cout << "  C++17的std::invoke更加简洁、通用，支持所有可调用类型\n";
} 